/* ====================================================================
 * (#)Header: PropertyTableCellRenderer.java
 * (#)Revision: 
 * (#)Date Created: Mar 2, 2007 12:07:22 AM
 * (#)Created By: Karol Wozniak
 * ====================================================================
 *
 * Copyright (c) 2007 karolak .  All rights reserved.
 *
 * ====================================================================
 * 
 * The software application represented here is the sole property of 
 * karolak. Its unauthorized utilization is expressly prohibited.
 * 
 * ====================================================================
 */
package com.karolak.client;

import java.awt.Component;
import java.lang.reflect.Method;
import java.text.Format;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;

import com.karolak.bean.BeanUtils;

/**
 * <code>PropertyTableCellRenderer</code> is used to ....
 * 
 * @author <a href="mailto:kwozniak@hotmail.com">Karol Wozniak</a>
 */
public class PropertyTableCellRenderer<T> extends DefaultTableCellRenderer {

	private static final long serialVersionUID = 1L;

	public enum AlienProperty {
		ROW("row") {
			@Override
			public Object getValue(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
				return row + 1;
			}
		},

		ROW_REVERTED("row_reverted") {
			@Override
			public Object getValue(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
				return table.getRowCount() - row;
			}
		};

		private String name;

		private AlienProperty(String name) {
			this.name = name;
		}

		public String getName() {
			return name;
		}

		public Object getValue(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
			return value;
		}

		public static boolean containsName(String name) {
			for (AlienProperty property : values()) {
				if (property.getName().equals(name)) {
					return true;
				}
			}
			return false;
		}

		public static AlienProperty getByName(String name) {
			for (AlienProperty property : values()) {
				if (property.getName().equals(name)) {
					return property;
				}
			}
			return null;
		}
	};

	private Class<T> typeClass;
	private Map<String, String> columnPropertyMapping = new LinkedHashMap<String, String>();
	private Map<String, Method> propertyAccessorMapping = new LinkedHashMap<String, Method>();
	private Map<String, Format> columnFormatMapping = new HashMap<String, Format>();

	public PropertyTableCellRenderer(Class<T> typeClass, Map<String, String> columnPropertyMapping) {
		if (columnPropertyMapping != null) {
			this.columnPropertyMapping = columnPropertyMapping;
		}

		if (typeClass == null) {
			return;
		}
		this.typeClass = typeClass;

		for (String propertyName : getColumnPropertyMapping().values()) {
			if (propertyName == null) {
				continue;
			}
			if (AlienProperty.containsName(propertyName)) {
				continue;
			}
			Method method = BeanUtils.getPropertyAccessor(getTypeClass(), propertyName);
			if (method != null) {
				propertyAccessorMapping.put(propertyName, method);
			}
		}
	}

	public PropertyTableCellRenderer(Class<T> typeClass, Map<String, String> columnPropertyMapping, Map<String, Format> columnFormatMapping) {
		this(typeClass, columnPropertyMapping);
		if (columnFormatMapping != null) {
			this.columnFormatMapping = columnFormatMapping;
		}
	}

	@Override
	public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {

		String columnName = table.getColumnName(column);
		String propertyName = getColumnPropertyMapping().get(columnName);
		setHorizontalAlignment(JLabel.CENTER);

		AlienProperty alienProperty = AlienProperty.getByName(propertyName);
		if (alienProperty != null) {
			value = alienProperty.getValue(table, value, isSelected, hasFocus, row, column);
		} else if (getTypeClass() != null && value != null && getTypeClass().isAssignableFrom(value.getClass())) {
			if (propertyName != null) {
				Method method = getPropertyAccessorMapping().get(propertyName);
				if (method != null) {
					Object propertyValue = BeanUtils.getPropertyValue(value, method);
					if (propertyValue != null) {
						Format format = getColumnFormatMapping().get(columnName);
						if (format != null) {
							value = format.format(propertyValue);
						} else {
							value = propertyValue.toString().trim();
						}
					} else {
						value = propertyValue;
					}
				}
			}
		}
		if (value != null) {
			setToolTipText(value.toString());
		} else {
			// investigate, if there is not empty tooltip, then old one does not
			// disappear
			setToolTipText("");
		}
		return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
	}

	protected Map<String, String> getColumnPropertyMapping() {
		return columnPropertyMapping;
	}

	protected Map<String, Method> getPropertyAccessorMapping() {
		return propertyAccessorMapping;
	}

	protected Class<T> getTypeClass() {
		return typeClass;
	}

	protected Map<String, Format> getColumnFormatMapping() {
		return columnFormatMapping;
	}
}
